#define _GNU_SOURCE 
#define _FILE_OFFSET_BITS 64 
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/falloc.h>
#include <fcntl.h>
#include <stdio.h>

#define BLOCK_SIZE 8192
#define MIN_SIZE 8192

int punchole(int fd, off_t pos, off_t r) {
	printf("Punch hole %llu %llu\n",pos,r);
	return fallocate(fd,FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE,pos,r);
}

int main(int argc, char** argv) {
	char buf[BLOCK_SIZE];
	if (argc>1) {
		int fd = open(argv[1],O_RDWR);
		int r;
		if (fd>0) {
			off_t pos = 0;
			off_t first_pos;
			off_t zc = 0;
			while ((r=read(fd,buf,BLOCK_SIZE))>0) {
			   int rpos = 0;
			   while (rpos<r) {
				if (buf[rpos]) {
				  if (zc>=MIN_SIZE) {
					if (punchole(fd,first_pos,zc)) {
						perror("punch hole");
						close(fd);
						return 1;
					}
				  }
			        	zc=0;
				} else {
				  if (zc==0) {
				    first_pos = pos+rpos;
				  }
				  zc++;
				}
				rpos++;
			   }
			  pos +=r;
			}
			if (zc>=MIN_SIZE) {
					punchole(fd,first_pos,zc);
			}
			close(fd);
			return 0;
		} else {
			perror("open");
		}
	} else {
		printf("%s [filename]\n",argv[0]);
	}
	return 2;		
}
